package repostiroy

import (
	"gorm.io/gorm"
	"shyxy-net/common/cache/lru"
	"shyxy-net/common/db/model-service/model"
)

type ModelInfoRepository interface {
	ListModelInfos() ([]*model.ModelInfo, error)
	FindModelInfoByModelName(modelName string) (*model.ModelInfo, error)
}

type modelInfoRepository struct {
	db *gorm.DB
}

func NewCachedModelInfoRepository(db *gorm.DB, cache *lru.LRU) ModelInfoRepository {
	dbRepo := NewModelInfoRepository(db)
	return newCachedModelInfoRepository(dbRepo, cache)
}
func NewModelInfoRepository(db *gorm.DB) ModelInfoRepository {
	return &modelInfoRepository{
		db: db,
	}
}

func (r *modelInfoRepository) ListModelInfos() ([]*model.ModelInfo, error) {
	var modelInfos []*model.ModelInfo
	return modelInfos, r.db.Find(&modelInfos).Error
}

func (r *modelInfoRepository) FindModelInfoByModelName(modelName string) (*model.ModelInfo, error) {
	var modelInfo *model.ModelInfo
	return modelInfo, r.db.Where("name = ?", modelName).First(&modelInfo).Error
}

type cachedModelInfoRepository struct {
	repo ModelInfoRepository
	lru  *lru.LRU
}

func newCachedModelInfoRepository(repo ModelInfoRepository, cache *lru.LRU) ModelInfoRepository {
	return &cachedModelInfoRepository{repo: repo, lru: cache}
}

func (c *cachedModelInfoRepository) ListModelInfos() ([]*model.ModelInfo, error) {
	if modelInfos, ok := c.lru.Get("model_infos"); ok {
		return modelInfos.([]*model.ModelInfo), nil
	}
	modelInfos, err := c.repo.ListModelInfos()
	if err != nil {
		return nil, err
	}
	c.lru.Add("model_infos", modelInfos)
	return modelInfos, nil
}

func (c *cachedModelInfoRepository) FindModelInfoByModelName(modelName string) (*model.ModelInfo, error) {
	if modelInfo, ok := c.lru.Get(modelName); ok {
		return modelInfo.(*model.ModelInfo), nil
	}
	modelInfo, err := c.repo.FindModelInfoByModelName(modelName)
	if err != nil {
		return nil, err
	}
	c.lru.Add(modelName, modelInfo)
	return modelInfo, nil
}
